// WifiTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "WifiPeek.h"
#include <iostream>
#include <afx.h>
#include <vector>
#include <wchar.h>
#include <string.h>
#include "HHPWiFiAPI.h"
#include <ntddndis.h>
#include <pm.h>
#include "gtest/gtest.h"
using namespace std;

WCHAR *APBSSID = L"Mobility-VLAN9";

class Wifi
{
private:
	CWifiPeek g_WifiPeek;
	vector<CString> adapters;
	BSSIDInfo nfo[128];
	DWORD dwTmp, dwCount;
	CString strCurrentAdapter;
	CString SplitString(CString strIn, TCHAR cSplitAt, int &iPos)
	{
		int i1, i2;

		if(iPos >= strIn.GetLength())
		{
			iPos=-1;
			return CString(_T(""));
		}

		i1=strIn.Find(cSplitAt, iPos);
		//not found?
		if(i1 == -1)
		{
			//return input string from iPos.
			i1=iPos;
			iPos=-1;
			return strIn.Mid(i1);
		}
		else
		{
			//found, return substring between (startpos, foundpos)
			i2=iPos;
			iPos=i1+1;

			if(i1 > i2)
			{
				return strIn.Mid(i2, i1-i2);
			}
			else
			{
				return strIn.Mid(i2);
			}
		}
	}
public:
	bool Init();
	bool getBSSID();
	bool connectToAP();
	bool close();
};

bool Wifi::Init()
{
	DevicePowerNotify(_T("{98C5250D-C29A-4985-AE5F-AFE5367E5006}\\TIWLNAPI1"),D0,POWER_NAME);
	//cout<<"DevicePowerNotify..."<<endl;
	Sleep(50);
	SetDevicePower(_T("{98C5250D-C29A-4985-AE5F-AFE5367E5006}\\TIWLNAPI1"),POWER_NAME,D0);
	//cout<<"SetDevicePower..."<<endl;
	cout<<"WIFI adapter is started!"<<endl;

	Sleep(3*1000);

	WCHAR buf[1024];
	DWORD dwSize = sizeof(buf);
	

	if(false == g_WifiPeek.GetAdapters(buf,dwSize) || dwSize == 0)
	{
		cerr<<"No adapter found!!"<<endl;
		return false;
	}
	else
	{
		//split adapter names
		CString strList, strName;
		int pos;

		strList = buf;
		pos = 0;
		//just one adapter
		if(strList.Find((_T(','),0) == -1))
		{
			adapters.push_back(strList);
		}
		else
			//no,a  list of adapters
		{
			do 
			{
				strName = SplitString(strList,_T(','),pos);
				adapters.push_back(strName);

			} while (strName != _T("")&&pos != -1);
		}
		return true;
	}
	
}

bool Wifi::getBSSID()
{
	if(adapters.size() == 0)
	{
		return false;
	}
	else
	{
		strCurrentAdapter = *(adapters.begin());	

		dwTmp=sizeof(nfo);
		dwCount=0;

		if(g_WifiPeek.GetBSSIDs(strCurrentAdapter.GetBuffer(), nfo, dwTmp, dwCount) && dwCount > 0)
		{
			//g_APData.ProcessInput(nfo, dwCount);
			for(int i=0;i<dwCount;++i)
				wcout<<i+1<<" : "<<nfo[i].SSID<<endl;
			return true;

		}//get BSSID ok
	}
	
}

bool Wifi::connectToAP()
{
	bool flag =false;
	if(strCurrentAdapter=="")
	{
		return false;
	}
	else
	{
		BSSIDInfo temp;
		for(int i=0;i<dwCount;++i)
		{
			if(wcscmp(nfo[i].SSID, APBSSID)==0)
			{
				temp = nfo[i];
				flag =	true; 
			}
		}
		if(flag == false)
		{
			cout<<"The specified AP not exists!!"<<endl;
			return false;
		}
		//set to peer or infrastructure depending on connected item type
		g_WifiPeek.PrepareToConnect(strCurrentAdapter.GetBuffer(), temp.Infastructure);
		g_WifiPeek.ConnectToAPName(strCurrentAdapter.GetBuffer(), temp.SSID);
		//renew DHCP ip address
		g_WifiPeek.RenewIpAddress(strCurrentAdapter.GetBuffer());

		return true;
	}
	
}

bool Wifi::close()
{
	Sleep(5*1000);
	
	if(strCurrentAdapter!="")
	{
		g_WifiPeek.Disconnect(strCurrentAdapter.GetBuffer());
		cout<<"Disconnect..."<<endl;
	}
	//  close the adapter
	DevicePowerNotify(_T("{98C5250D-C29A-4985-AE5F-AFE5367E5006}\\TIWLNAPI1"),D4,POWER_NAME);
	//cout<<"DevicePowerNotify..."<<endl;
	Sleep(50);
	SetDevicePower(_T("{98C5250D-C29A-4985-AE5F-AFE5367E5006}\\TIWLNAPI1"),POWER_NAME,D4);
	//cout<<"SetDevicePower..."<<endl;
	cout<<"WIFI adapter is closed!"<<endl;

	return true;
}

int _tmain(int argc, _TCHAR* argv[])
{
	APBSSID = argv[argc-1];
	wcout<<APBSSID<<endl;

	testing::InitGoogleTest(&argc, argv);
	return RUN_ALL_TESTS();
}

class WifiTest : public testing::Test
{
protected:
	static void SetUpTestCase()
	{
		wifi = new Wifi();
		cout<<"start"<<endl;
	}
	static void TearDownTestCase()
	{
		delete wifi;
	}
	static Wifi* wifi;
};
Wifi* WifiTest::wifi = NULL;

TEST_F(WifiTest,Init)
{
	EXPECT_EQ(1,wifi->Init());
	Sleep(3000);
}

TEST_F(WifiTest,getAPList)
{
	EXPECT_EQ(1,wifi->getBSSID());
	Sleep(3000);
}

TEST_F(WifiTest,connectToAP)
{
	EXPECT_EQ(1,wifi->connectToAP());
	Sleep(3000);
}

TEST_F(WifiTest,close)
{
	EXPECT_EQ(1,wifi->close());
	Sleep(3000);
}


